package com.douqu.game.core.controller;

import com.douqu.game.core.e.E_PlayerStatus;
import com.douqu.game.core.entity.Skill;
import com.douqu.game.core.entity.battle.*;
import com.douqu.game.core.container.PlayerContainer;
import com.douqu.game.core.entity.sprite.Sprite;
import com.douqu.game.core.factory.ConstantFactory;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.protobuf.SGMainProto;
import com.douqu.game.core.protobuf.SGWarProto;
import org.apache.log4j.Logger;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created by bean on 2017/7/28.
 */
public class BattleParentController extends PlayerContainer {

    Logger logger = Logger.getLogger(BattleParentController.class);


    /** 观战者队伍 */
    public final static int TEAM_SPECTATOR = -1;
    /** 队伍1 */
    public final static int TEAM_1 = 1;
    /** 队伍2 */
    public final static int TEAM_2 = 2;
    /** 战斗中最大行数(横) */
    public final static int MAX_ROW = 10;//必须双数
    /** 战斗中最大列数(竖) */
    public final static int MAX_COL = 20;
    /** 队伍1的主将位置 */
    public final static int[][] TEAM_1_MASTER = {{(MAX_ROW-1)>>1,0},{MAX_ROW>>1,0}};
    /** 队伍2的主将位置 */
    public final static int[][] TEAM_2_MASTER = {{(MAX_ROW-1)>>1,MAX_COL-1},{MAX_ROW>>1,MAX_COL-1}};

    /**
     * ID生成
     */
    public int createSoldierUniqueId = 0;

    /**
     * 主将ID
     */
    public int createMasterUniqueId = createSoldierUniqueId + 1000;

    /**
     * 左上
     */
    protected Position leftTop;
    /**
     * 左下
     */
    protected Position leftBottom;
    /**
     * 右上
     */
    protected Position rightTop;
    /**
     * 右下
     */
    protected Position rightBottom;

    protected String id;
    /**
     * 战斗类型
     */
    protected SGCommonProto.E_BATTLE_TYPE battleType;

    /**
     * 观战的人
     */
    protected List<PlayerController> spectators = new CopyOnWriteArrayList<>();


    /**
     * 一局最长的时间
     */
    protected int maxBattleTime;

    /**
     * 战斗创建时间
     */
    protected int createTime;

    /**
     * 战斗开始时间
     */
    protected int startTime;

    protected int endTime;

    /**
     * 战斗持续时间
     */
    protected int battleTime;

    /**
     * 当前战斗状态
     */
    protected int status;

    protected PlayerController player;

    protected SpriteController target;

    /**
     * 用来通知主服务器的数据
     */
    protected BattleControllerInfo battleInfo;

    public BattleParentController(String battleId, PlayerController player, SpriteController target, SGCommonProto.E_BATTLE_TYPE battleType,
                                  SGCommonProto.Pos leftBottom, SGCommonProto.Pos rightTop)
    {
        this.id = battleId;
        this.player = player;
        this.target = target;
        this.battleType = battleType;

        this.leftBottom = new Position(leftBottom);
        this.rightTop = new Position(rightTop);
        this.leftTop = new Position(leftBottom.getX(), rightTop.getY());
        this.rightBottom = new Position(rightTop.getX(), leftBottom.getY());

        player.setParent(this);
        player.setStatus(E_PlayerStatus.BATTLE_WAIT_START);
        target.setParent(this);
        target.setStatus(E_PlayerStatus.BATTLE_WAIT_START);
    }

    public void init(){}

    public boolean isEnd()
    {
        if(player == null || target == null || player.getAttachment() == null || target.getAttachment() == null)
            return true;

        if(player.getAttachment().isDie() || target.getAttachment().isDie())
            return true;

        return false;
    }

    public void end(int winTeam)
    {


    }


    /**
     * 是否是真人对战
     * @return
     */
    public boolean isRealPlayerBattle()
    {
        return battleType == SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_PVP_ARENA;
    }


    public boolean isReady()
    {
        if(isRealPlayerBattle())
            return player.getAttachment().isReady() && target.getAttachment().isReady();
        else
            return player.getAttachment().isReady();
    }

    public int getWinTeam()
    {
        if(player.getAttachment().isDie())
            return target.getAttachment().getTeamNo();

        if(target.getAttachment().isDie())
            return player.getAttachment().getTeamNo();

        return 0;
    }


    public Position getMiddlePos(int teamNo)
    {
        float r1 = (float) (Math.random() * 4);
        float r2 = (float) (Math.random() * 4 - 2);
        if(teamNo == TEAM_1)
        {
            return new Position(leftBottom.getX() + r1, (leftTop.getY() - leftBottom.getY())/2 + leftBottom.getY() + r2);
        }
        else
        {
            return new Position(rightBottom.getX() - r1, (rightTop.getY() - rightBottom.getY())/2 + rightBottom.getY() + r2);
        }
    }

    public void removeBattleSoldier(BattleAObject soldier)
    {

    }


    public List<BattleAObject> getSkillTargets(BattleSkill skill)
    {
        return null;
    }

    public List<BattleAObject> getSkillTargets(BattleSkill skill, Position position)
    {
        return null;
    }

    public List<BattleAObject> getSkillTargets(BattleSkill skill, List<BattleAObject> targets, boolean checkRange)
    {
        return null;
    }


    /**
     * 检测种族获得星星
     * @param race
     */
    public void checkStar(SpriteBattleTmp spriteBattleTmp, int race)
    {}



    /**
     * 通知兵相遇要开战了
     * @param attacker
     * @param target
     */
    public void sendSoldierBattleStart(BattleAObject attacker, BattleAObject target)
    {
        SGWarProto.S2C_SoldierBattleStart.Builder data = SGWarProto.S2C_SoldierBattleStart.newBuilder();
        data.setAttackId(attacker.getId());
        data.setAttackPos(attacker.getPosition().parsePos());
        data.setTargetId(target.getId());
        data.setTargetPos(target.getPosition().parsePos());
        dispatchMsg(SGMainProto.E_MSG_ID.MsgID_War_SoldierBattleStart_VALUE, data.build().toByteArray());

        logger.info("BattleParentController sendSoldierBattleStart attacker:" + attacker + " target:" + target);
    }

    /**
     * 通知使用技能结果
     * @param skillId
     * @param releaser
     * @param targetId
     */
    public void sendUseSkill(int skillId, int releaser, int targetId, int effectTime, Position position)
    {
        SGWarProto.S2C_UseSkill.Builder data = SGWarProto.S2C_UseSkill.newBuilder();
        data.setSkillId(skillId);
        data.setReleaserId(releaser);
        data.addTargetId(targetId);
        data.setEffectTime(effectTime);
        if(position != null)
            data.setTargetPos(position.parsePos());

        dispatchMsg(SGMainProto.E_MSG_ID.MsgID_War_UseSkill_VALUE, data.build().toByteArray());

        logger.info("BattleParentController sendUseSkill skillId:" + skillId + " target:" + targetId + " 生效时间:" + effectTime + " 目标点:" + position);
    }

    /**
     * 通知使用技能结果
     * @param skillId
     * @param releaser
     * @param targets
     */
    public void sendUseSkill(int skillId, int releaser, List<BattleAObject> targets, int effectTime, Position position)
    {
        SGWarProto.S2C_UseSkill.Builder data = SGWarProto.S2C_UseSkill.newBuilder();
        data.setSkillId(skillId);
        data.setReleaserId(releaser);

        if(targets != null)
        {
            for(BattleAObject battleAObject : targets)
            {
                data.addTargetId(battleAObject.getId());
            }
        }

        data.setEffectTime(effectTime);
        if(position != null)
            data.setTargetPos(position.parsePos());

        dispatchMsg(SGMainProto.E_MSG_ID.MsgID_War_UseSkill_VALUE, data.build().toByteArray());

        logger.info("BattleParentController sendUseSkill skillId:" + skillId + " target:" + targets + " 生效时间:" + effectTime + " 目标点:" + position);

    }

    /**
     * 通知伤害
     * @param target
     * @param damage 伤害值 负数为减血 正数为加血
     * @param hp 伤害后的血
     */
    public void sendDamage(int target, int damage, int hp)
    {
        if(damage == 0)
            return;

        SGWarProto.S2C_DoDamage.Builder data = SGWarProto.S2C_DoDamage.newBuilder();
        data.addSpriteDamage(createDamageInfo(target,damage,hp));

        dispatchMsg(SGMainProto.E_MSG_ID.MsgID_War_DoDamage_VALUE, data.build().toByteArray());
    }

    public SGCommonProto.SpriteDamage.Builder createDamageInfo(int target, int damage, int hp)
    {
        SGCommonProto.SpriteDamage.Builder spriteDamage = SGCommonProto.SpriteDamage.newBuilder();
        spriteDamage.setTargetId(target);
        spriteDamage.setDamage(damage);
        spriteDamage.setHp(hp);

        return spriteDamage;
    }



//    public void sendAttributeUpdate(int id, int change, int value)
//    {
//
//    }



    public int getSoldierUniqueId()
    {
        return ++createSoldierUniqueId;
    }


//    public int getMasterUniqueId()
//    {
//        return ++createMasterUniqueId;
//    }


    public void addSoldier(BattleAObject soldier){

    }

    /**
     * 转发容器内所有的消息
     * @param
     */
    @Override
    public void dispatchMsg(int code, byte[] data)
    {
        super.dispatchMsg(code, data);

        for(PlayerController playerController : spectators)
        {
            playerController.sendMsg(code ,data);
        }
    }

    public void destory()
    {
        for(PlayerController playerController : playerList)
        {
            playerController.destroy();
        }
    }


    public String getId() {
        return id;
    }

    public SGCommonProto.E_BATTLE_TYPE getBattleType() {
        return battleType;
    }

    public PlayerController getPlayer() {
        return player;
    }

    public void setPlayer(PlayerController player) {
        this.player = player;
    }

    public SpriteController getTarget() {
        return target;
    }

    public void setTarget(SpriteController target) {
        this.target = target;
    }

    public BattleControllerInfo getBattleInfo() {
        return battleInfo;
    }
}
